﻿using BackupContracts.Services;
using BackupContracts.Sql;
using BackupContracts.Tasks;
using BackupManager.Configuration;
using BackupManager.Sql;
using BackupManager.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BackupManager.Services
{
    public class BackupService : IBackupService
    {
        public void UpsertSqlServer(SqlServer sqlServer)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            sqlDatabaseProvider.UpsertServer(sqlServer);
        }

        public void DeleteSqlServer(string serverId)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            sqlDatabaseProvider.DeleteServer(serverId);
        }

        public List<SqlServer> ListSqlServers()
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            return sqlDatabaseProvider.ListServers();
        }

        public List<SqlDatabase> ListSqlDatabases(string serverId)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            return sqlDatabaseProvider.FetchDatabases(serverId);
        }

        private string GetEncryptionKey()
        {
            return ConfigManager.Instance.EncryptionKey;
        }

        private CloudStorageAccount GetStorageAccount()
        {
            return CloudStorageAccount.Parse(ConfigManager.Instance.StorageConnectionString);
        }

        public void UpsertTask(Task task)
        {
            var storageAccount = GetStorageAccount();
            var taskProvider = new TaskProvider(storageAccount);
            taskProvider.UpsertTask(task);
        }

        public void DeleteTask(string taskId)
        {
            var storageAccount = GetStorageAccount();
            var taskProvider = new TaskProvider(storageAccount);
            taskProvider.DeleteTask(taskId);
        }

        public List<Task> ListTasks()
        {
            var storageAccount = GetStorageAccount();
            var taskProvider = new TaskProvider(storageAccount);
            var allTasks = taskProvider.ListTasks();
            List<SqlServer> allServers = null;
            foreach (var task in allTasks)
            {
                if (task.Actions != null)
                {
                    foreach (var action in task.Actions.OfType<SqlBackupTaskAction>())
                    {
                        if (action.Database != null)
                        {
                            if (allServers == null)
                            {
                                var encryptionKey = GetEncryptionKey();
                                var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
                                allServers = sqlDatabaseProvider.ListServers();
                            }
                            action.Database.Server = allServers.FirstOrDefault((s) => s.Id.Equals(action.Database.ServerId));
                        }
                    }
                }
            }
            return allTasks;
        }


        public void CopyAndBackupToBlob(string serverName, string databaseName, string loginId, string password, string storageAccount, string storageKey, string container, int maxHistory)
        {
            var cloudStorageAccount = new CloudStorageAccount(new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(storageAccount, storageKey), true);
            SqlDatabaseProvider.CopyAndBackupToBlob(serverName, databaseName, loginId, password, cloudStorageAccount, container, maxHistory);
        }

        public bool CheckCredentials()
        {
            return true;
        }


        public List<SqlDatabaseBackup> ListDatabaseBackups(string serverName, string databaseName)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            return sqlDatabaseProvider.ListDatabaseBackups(serverName, databaseName);
        }

        public List<SqlDatabase> ListDatabases(string serverName)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            return sqlDatabaseProvider.ListDatabases(serverName);
        }


        public List<SqlDatabaseBackupLog> ListDatabaseBackupLogs(string serverName, string databaseName, string backupId)
        {
            var storageAccount = GetStorageAccount();
            var encryptionKey = GetEncryptionKey();
            var sqlDatabaseProvider = new SqlDatabaseProvider(storageAccount, encryptionKey);
            return sqlDatabaseProvider.ListDatabaseBackupLogs(serverName, databaseName, backupId);
        }


        public string GetPublicBlobUrl(string blobUrl)
        {
            var storageAccount = GetStorageAccount();
            var blobClient = storageAccount.CreateCloudBlobClient();
            var blob = blobClient.GetBlobReferenceFromServer(new Uri(blobUrl));
            return blobUrl + blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                SharedAccessExpiryTime = DateTime.Now.AddMinutes(30),
                Permissions = SharedAccessBlobPermissions.Read,
            });
        }
    }
}
